package com.px.service;

import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.px.client.CommodityFeignClient;
import com.px.client.OrderFeignClient;
import com.px.client.PayFeignClient;
import com.px.config.AlipayConfig;
import com.px.pojo.ShCommodity;
import com.px.pojo.ShGoodsTempStock;
import com.px.pojo.ShOrder;
import com.px.pojo.ShTrade;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Service
@Slf4j
public class PayServiceImpl implements PayService {

    @Resource
    private AlipayConfig alipayConfig;
    
    @Resource
    private OrderFeignClient orderFeignClient;
    
    @Resource
    private CommodityFeignClient commodityFeignClient;
    
    @Resource
    private PayFeignClient payFeignClient;

    @Override
    public String createAliForm(Integer orderId) throws Exception {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(
                alipayConfig.getUrl(),
                alipayConfig.getAppID(),
                alipayConfig.getRsaPrivateKey(),
                alipayConfig.getFormat(),
                alipayConfig.getCharset(),
                alipayConfig.getAlipayPublicKey(),
                alipayConfig.getSignType());
        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        //处理同步通知的请求网址
        alipayRequest.setReturnUrl(alipayConfig.getReturnUrl());
        //处理异步通知的请求网址
        alipayRequest.setNotifyUrl(alipayConfig.getNotifyUrl());
        //根据订单ID获取订单对象
        ShOrder shOrder = orderFeignClient.selectOrderByOrderId(orderId);
        //根据订单对象中的商品ID获取商品对象
        ShCommodity shCommodity = commodityFeignClient.selectGoodsById(shOrder.getCommodityId());
        alipayRequest.setBizContent("{\"out_trade_no\":\""+ shOrder.getOrderNo() +"\","
                + "\"total_amount\":\""+ shOrder.getAmount() +"\","
                + "\"subject\":\""+ shCommodity.getCommodityName() +"\","
                + "\"body\":\""+"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        //请求
        return alipayClient.pageExecute(alipayRequest).getBody();
    }

    //验签
    @Override
    public boolean validateAliPay(Map<String, String[]> requestParams) throws Exception {
        Map<String,String> params = new HashMap<>();
        for (Iterator<String> ite = requestParams.keySet().iterator();ite.hasNext();){
            String name = ite.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i=0;i<values.length;i++){
                valueStr = (i==values.length-1)?valueStr+values[i] :valueStr + values[i]+",";
            }
            //解决乱码
            valueStr =new String(valueStr.getBytes("ISO-8859-1"),"UTF-8");
            params.put(name,valueStr);
        }
        //调用SDK验证签名
        return AlipaySignature.rsaCheckV1(params,alipayConfig.getAlipayPublicKey(),alipayConfig.getCharset(),alipayConfig.getSignType());
    }

    //判断交易记录表中是否有该订单的记录
    @Override
    public boolean validateDealPaySuccess(String orderNo) throws Exception {
        Map<String,Object> map = new HashMap<>();
        map.put("orderNo",orderNo);
        Integer count = payFeignClient.selectTradeCountByTradeNo(map);
        if (count>0){
            return true;
        }
        return false;
    }

    @Override
    public String dealPaySuccess(String orderNo, String tradeNo, Integer payMethod) throws Exception {
        ShOrder shOrder = orderFeignClient.selectOrderByOrderNo(orderNo);
        //保存交易记录
        saveTrade(shOrder.getAmount(),orderNo,tradeNo,payMethod);
        //修改订单状态
        updateOrder(shOrder,tradeNo);
        //修改库存状态
        updateStock(shOrder.getStockId());
        return String.valueOf(shOrder.getOrderId());
    }

    @Override
    public String dealPaySuccessReFund(String orderNo, String tradeNo) throws Exception {
        ShOrder shOrder = orderFeignClient.selectOrderByOrderNo(orderNo);
        //删除交易记录
        deleteTrade(tradeNo);
        //修改订单状态
        updateOrderReFund(shOrder);
        //修改库存状态
        updateStockReFund(shOrder.getStockId());
        return String.valueOf(shOrder.getOrderId());
    }

    private void updateStockReFund(Integer stockId) throws Exception {
        ShGoodsTempStock tempStock = orderFeignClient.selectGoodsTempStock(stockId);
        tempStock.setUpdatedTime(new Date());
        tempStock.setStatus(2);
        orderFeignClient.updateStock(tempStock);
    }

    private void updateOrderReFund(ShOrder shOrder) throws Exception {
        shOrder.setPayStatus(2);
        shOrder.setUpdateTime(new Date());
        orderFeignClient.updateOrder(shOrder);
    }

    private void deleteTrade(String tradeNo) throws Exception{
        payFeignClient.deleteByTradeNo(tradeNo);
    }

    @Override
    public ShOrder selectOrderByOrderNo(String orderNo) throws Exception {
        return orderFeignClient.selectOrderByOrderNo(orderNo);
    }

    @Override
    public ShOrder selectOrderById(Integer orderId) throws Exception {
        return orderFeignClient.selectOrderByOrderId(orderId);
    }

    //添加交易记录
    private void saveTrade(double amount,String orderNo,String tradeNo,Integer payMethod) throws Exception{
        ShTrade shTrade = new ShTrade();
        shTrade.setAmount(amount);
        shTrade.setPayMethod(payMethod);
        shTrade.setOrderNo(orderNo);
        shTrade.setTradeNo(tradeNo);
        shTrade.setCreatedTime(new Date());
        payFeignClient.saveTrade(shTrade);
    }

    //修改支付成功后的订单状态
    private void updateOrder(ShOrder shOrder,String tradeNo) throws Exception{
        shOrder.setPayStatus(1);
        shOrder.setUpdateTime(new Date());
        shOrder.setAliTradeNo(tradeNo);
        orderFeignClient.updateOrder(shOrder);
    }

    //修改支付成功后库存中的额订单状态
    private void updateStock(Integer stockId) throws Exception{
        ShGoodsTempStock tempStock = orderFeignClient.selectGoodsTempStock(stockId);
        tempStock.setStatus(1);
        tempStock.setUpdatedTime(new Date());
        orderFeignClient.updateStock(tempStock);
    }

}
